#include "config.h"
#include "interface.h"
#include "devapi.h"
#include <stdlib.h>
#include "txn_par.h"
#include "platform.h"
#include "apitrans.h"
#include "result.h"
#include "arq_cmd.h"
#include "emvapi.h"


emv_fun_t * pemv = NULL;


int Emv_init(unsigned char *cmd, int len)
{
    int ret = 0;
    int fd1;
    int fd2;
    uint8_t name[48] = {0};
    uint8_t kernel = cmd[0];
    
 debug_aux("%s(), %d\r\n", __func__, __LINE__);         
    if ((pemv = sys_load_library("emvlib")) == NULL) {
        ret = ERR_EMV_LIB_LOAD;
        goto end;
    }

    init_emv_inf();

    if ((ret = init_emv_files(kernel)) < 0) {
        
        sprintf( (char*)name, "/appfs/kernel%d.app", kernel);
        fd1 = open( (char*)name, O_RDONLY);
        
        sprintf( (char*)name, "/appfs/%s", CAPK_NAME);
        fd2 = open( (char*)name, O_RDONLY);
        
    	if(fd1 < 0 && fd2 < 0)
        {
    		ret = ERR_EMV_CAPK_KERNEL_FILE;
    	}else if(fd1 < 0)
    	{
            ret = ERR_EMV_KERNEL_FILE;
        }else
        {
            ret = ERR_EMV_CAPK_FILE;
        }

    }

end:    
    memcpy( cmd, &ret, 2);
    return 2;
}


#if defined(_IS_BCTE_TEST)

int Emv_get_ec_balance(unsigned char *cmd, int len)
{
    unsigned long tag[] = {0x9F5D, 0x9f79, 0x9f77};
    int ret = 0;
    unsigned char outbuf[20] = {0};
    int outbufLen;
    int offset = 0;
debug_aux("%s(), %d,\r\n", __func__, __LINE__);

    if( pemv==NULL )
    {
        ret = ERR_EMV_LIB_LOAD;
        offset = 2;
        goto end;
    }
    
    ret = get_ec_balance(cmd[1]);
    
debug_aux("%s(), %d, ret = %d\r\n", __func__, __LINE__, ret);      
    if(ret != 0)
    {      
        offset = 2;
        goto end;
    }
    
    if((outbufLen = pemv->emv_get_data( tag + cmd[0], 1, outbuf, 100 )) <= 0 ){
debug_aux("%s(), %d,\r\n", __func__, __LINE__);   
        ret = ERR_EMV_EC;
        offset = 2;
        goto end;
    }
    
    memcpy( cmd + offset, &ret, 2);
    
    offset = 2;
    
    cmd[offset] = outbufLen - 3;
    
    offset += 1;
    
    memcpy( cmd + offset, outbuf + 3, outbufLen - 3);
    
	offset += outbufLen - 3;
    
debug_aux_hex("data:", cmd, offset);

end:
    memcpy( cmd + offset, &ret, 2);
    return offset;
    
}



int Emv_get_log_fmt(unsigned char *cmd, int inlen)
{
    int log_type;
    int pos_entry_type;
    int ret = 0;
    int offset = 0;
    
debug_aux("%s(), %d\r\n", __func__, __LINE__); 
    if( pemv==NULL )
    {
        ret = ERR_EMV_LIB_LOAD;
        offset = 2;
        goto end;
    }
    log_type = cmd[0];
    
    pos_entry_type = cmd[1];


    ret = get_log_fmt( pos_entry_type, log_type, cmd + 2,cmd + 3,cmd + 4);
    
    if(ret != 0)
    {
        offset = 2;
        goto end;
    }
    
    offset = cmd[3] + 4;
end:    
    memcpy( cmd, &ret, 2);
    
    return offset;
}

int Emv_get_log_data(unsigned char *cmd, int inlen)
{
    int log_type;
    int pos_entry_type;
    uint8_t rec;
    int offset = 0;
    int ret = 0;
    
debug_aux("%s(), %d\r\n", __func__, __LINE__); 
    if( pemv==NULL )
    {
        ret = ERR_EMV_LIB_LOAD;
        offset = 2;
        goto end;
    }
    
    log_type = cmd[0];
    
    pos_entry_type = cmd[1];
    
    rec = cmd[2];
    
    ret = get_log_data( pos_entry_type, log_type, rec,cmd + 2,cmd + 3);
    
    if(ret != 0)
    {
       offset = 2;
       goto end;
    }
    
    offset = cmd[2] + 3;
end:    
    memcpy( cmd, &ret, 2);
    return offset;
}


int Emv_go_online(unsigned char *cmd, int len)
{
    int in_len,out_len;
	int offset = 0;
	int ret = 0;

	in_len = BCDtoDec(cmd + offset,2);
	offset += 2;
debug_aux("%s(), %d, ret = %d\r\n", __func__, __LINE__); 
    out_len = go_online(cmd + offset, in_len, cmd + 4);

    offset = 0;
	memcpy( cmd + offset, &ret, 2);
    if(out_len < 0)
    {
        ret = ERR_EMV_ONLINE;
        memcpy( cmd + offset, &ret, 2);
        return 2;
    }
    
    offset += 2;
    DectoBCD( out_len, cmd + offset, 2);
    offset += 2;

debug_aux("%s(), %d :", __func__, __LINE__);       
debug_aux_hex("", cmd , offset + out_len);      
	return offset + out_len;
}

int Emv_update_capk(unsigned char *cmd, int len)
{
    int ret = 0;
    debug_aux("%s(), %d\r\n", __func__, __LINE__); 
    ret = update_capk();
    memcpy( cmd, &ret, 2);
    return 2;
}

int Emv_get_version(unsigned char *cmd, int inlen)
{
    int ret = 0;
    int offset = 0;

debug_aux("%s(), %d\r\n", __func__, __LINE__); 
    if( pemv==NULL )
    {
        ret = ERR_EMV_LIB_LOAD;
        
        offset = 2;
        
        goto end;
    }
    
    sprintf( (char*)cmd + 2, "%s", pemv->emv_version( ));
    
    offset = 2 + strlen(pemv->emv_version( ));
end:
    memcpy( cmd, &ret, 2);
    
    return offset;
}

int Emv_clear_translog(unsigned char *cmd, int inlen)
{
    int ret = 0;
    char path[EMV_PATH_NAME_MAX + EMV_FILE_NAME_MAX];

debug_aux("%s(), %d\r\n", __func__, __LINE__);   

    sprintf(path, "%s%s", CONFIG_PATH, LOG_NAME);
    
    unlink( path );
    
    memcpy( cmd, &ret, 2);
    
    return 2;
}


int Emv_get_kel_checksum(unsigned char *cmd, int len)
{
	uint8_t kernel;
	uint8_t name[48] = {0};
    int fd;
	emv_param_t par;
	uint16_t ret= 0;
	uint32_t crc = 0;
	uint8_t offset = 0;
	
	kernel = cmd[0];
    
	sprintf( (char*)name, "/appfs/kernel%d.app", kernel);

	fd = open( (char*)name, O_RDONLY);
    
	if(fd < 0){
		ret = ERR_EMV_KERNEL_FILE;
		memcpy(cmd,&ret,2);
		return 2;
	}
    
	len = read(fd, &par, sizeof (par));
    
	if(len != sizeof (par)){
		ret = ERR_EMV_KERNEL_FILE_READ;
		memcpy(cmd,&ret,2);
		close(fd);
		return 2;
	}
	close(fd);
    
	memcpy(name, par._ics, 7);		
    
	name[7] = par._type;
    
	memcpy(name + 8, par._cap, 3);
    
	memcpy(name + 11, par._add_cap, 5);
    
	crc = crc32(0, (uint8_t *)name, 16);
    
	memcpy(cmd,&ret,2);
	offset += 2;
    
	DectoBCD( crc, cmd + offset,8);   
	offset += 8;
    
	return offset;
    
}

#else

int Emv_get_ec_balance(unsigned char *cmd, int len){}
int Emv_get_log_fmt(unsigned char *cmd, int len){}
int Emv_get_log_data(unsigned char *cmd, int len){}
int Emv_go_online(unsigned char *cmd, int len){}
int Emv_update_capk(unsigned char *cmd, int len){}
int Emv_get_version(unsigned char *cmd, int inlen)
{
    int ret = 0;
    int offset = 0;

debug_aux("%s(), %d\r\n", __func__, __LINE__); 
    if( pemv==NULL )
    {
        ret = ERR_EMV_LIB_LOAD;
        
        offset = 2;
        
        goto end;
    }
    
    sprintf( (char*)cmd + 2, "%s", pemv->emv_version( ));
    
    offset = 2 + strlen(pemv->emv_version( ));
end:
    memcpy( cmd, &ret, 2);
    
    return offset;
}

int Emv_clear_translog(unsigned char *cmd, int len){}
int Emv_get_kel_checksum(unsigned char *cmd, int len){}

#endif

static func_t Emv_fun[] = {
	NULL,Emv_init, Emv_get_ec_balance, Emv_get_log_fmt, \
		 Emv_get_log_data, Emv_go_online, Emv_update_capk,\
         Emv_get_version, Emv_clear_translog, Emv_get_kel_checksum
};


int cmd_emv_oper(uint8_t cmd, uint8_t *buf, int len)
{
	if(cmd < 0x01 || cmd > FUN_SIZE(Emv_fun))
		return -5;
	return Emv_fun[(int)cmd]((uint8_t*)buf, len);
}



